home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir39 / borfix.zip / TI1299.ASC < prev    next >
Text File  |  1994-08-23  |  8KB  |  269 lines

  1.   /*************************************************************
  2.     This program shows how to use XMS.  In this example, we
  3.     simulate a large array in XMS and show that it works by
  4.     writing values into it and reading them out again.
  5.     Compile in any model but HUGE and make sure you have
  6.     HIMEM.SYS or another XMS manager loaded.
  7.     Many thanks to Ray Duncan, whose book "Extending DOS"
  8.     (written with many others) was very helpful.
  9.   ************************************************************/
  10.  
  11.   #ifdef __HUGE__
  12.   #error This example cannot be compiled in the huge memory model.
  13.   #endif
  14.  
  15.   #include <dos.h>
  16.   #include <stdio.h>
  17.   #include <stdlib.h>
  18.   #include <alloc.h>
  19.  
  20.   #define TRUE 1
  21.   #define FALSE 0
  22.  
  23.   // BLOCKSIZE will be the size of our real-memory buffer that
  24.   // we'll swap XMS through (must be a multiple of 1024, since
  25.   // XMS is allocated in 1K chunks.) Can be > 64K as implemented
  26.  
  27.   #define BLOCKSIZE (1024L*16)
  28.  
  29.   // XMSParms is a structure for copying information to and from
  30.   // real-mode memory to XMS memory
  31.  
  32.   struct parmstruct
  33.   {
  34.       // blocklength is the size in bytes of block to copy
  35.  
  36.       unsigned long blockLength;
  37.  
  38.        // sourceHandle is the XMS handle of source; 0 means that
  39.        // sourcePtr will be a 16:16 real-mode pointer, otherwise
  40.        // sourcePtr is a 32-bit offset from the beginning of the
  41.        // XMS area that sourceHandle points to
  42.  
  43.        unsigned int sourceHandle;
  44.  
  45.        far void *sourcePtr;
  46.  
  47.        // destHandle is the XMS handle of destination; 0 means that
  48.        // destPtr will be a 16:16 real-mode pointer, otherwise
  49.        // destPtr is a 32-bit offset from the beginning of the XMS
  50.        // area that destHandle points to
  51.  
  52.        unsigned int destHandle;
  53.       far void *destPtr;
  54.   } XMSParms;
  55.  
  56.   // XMSFunc is a function pointer we'll use to call into the XMS
  57.   // manager
  58.   void far (*XMSFunc) (void);
  59.   // XMSBuf is the real-mode memory buffer for transfers to and
  60.   // from XMS.  Make it a huge * instead of a far * if BLOCKSIZE
  61.   // is >= 64K
  62.   unsigned long huge *XMSBuf;
  63.   // XMSHandle is the handle we'll use to refer to our
  64.   // XMS allocation
  65.   // when talking to the XMS manager
  66.   unsigned int XMSHandle;
  67.  
  68.   // a flag which says whether the current buffer has been
  69.   // written into or not
  70.   char curBlockDirty=FALSE;
  71.   // the part of our XMS allocation that is currently copied
  72.   // into real memory
  73.   int curBlock=-1;
  74.  
  75.   // returns TRUE if XMS present, FALSE otherwise
  76.   char XMSCheck()
  77.   {
  78.        _AX=0x4300;
  79.        geninterrupt(0x2F);
  80.        return (_AL==0x80);
  81.   }
  82.  
  83.   // GetXMSEntry sets XMSFunc to the XMS Manager entry point
  84.   // so we can call it later
  85.  
  86.   void GetXMSEntry(void)
  87.   {
  88.        _AX=0x4310;
  89.        geninterrupt(0x2F);
  90.        XMSFunc= (void (far *)(void)) MK_FP(_ES,_BX);
  91.   }
  92.  
  93.   // XMSSize returns the total kilobytes available, and the size
  94.   // in kilobytes of the largest available block
  95.  
  96.   void XMSSize(int *kbAvail, int *largestAvail)
  97.   {
  98.        _AH=8;
  99.        (*XMSFunc)();
  100.        *largestAvail=_DX;
  101.        *kbAvail=_AX;
  102.   }
  103.  
  104.   char GetBuf(void)
  105.   {
  106.        XMSBuf=(unsigned long far *) farmalloc(BLOCKSIZE);
  107.        if (XMSBuf==NULL)
  108.        {
  109.             printf("Couldn't allocate %u bytes for real-memory buffer\n",BLOCKSIZE);
  110.             return FALSE;
  111.        }
  112.        return TRUE;
  113.   }
  114.  
  115.   char AllocXMS(unsigned long numberBytes)
  116.   {
  117.        int numBlocks;
  118.        // divide by BLOCKSIZE to get number of blocks
  119.        numBlocks=(int) (numberBytes/BLOCKSIZE);
  120.        if ((numberBytes%BLOCKSIZE) != 0) ++numBlocks;
  121.        _DX=(int) (numBlocks*(BLOCKSIZE/1024));
  122.        _AH=9;
  123.        (*XMSFunc)();
  124.        if (_AX==0)
  125.        {
  126.             printf("Could not allocate %u %u-byte blocks of XMS\n",
  127.                  numBlocks,BLOCKSIZE);
  128.             return FALSE;
  129.        }
  130.        XMSHandle=_DX;
  131.        return TRUE;
  132.   }
  133.  
  134.   // CleanUpAndLeave() frees up the XMS handle that we allocated
  135.  
  136.   void CleanUpAndLeave(void)
  137.   {
  138.        printf("Cleaning up and leaving.\n");
  139.        _DX=XMSHandle;
  140.        _AH=0x0A;
  141.        (*XMSFunc)();
  142.        exit(1);
  143.   }
  144.  
  145.   // GetCorrectBlock() makes sure that the current block stored
  146.   // in the buffer XMSBuf is the correct block by swapping the
  147.   // current block out and bringing in a new block
  148.  
  149.   void GetCorrectBlock(unsigned int block)
  150.   {
  151.        // curBlockDirty is checked for an optimization:  we write
  152.        // out the current buffer back out to XMS only if it's
  153.        // "dirty" (been written into).
  154.        if (curBlockDirty)
  155.        {
  156.             // write dirty block from XMSBuf out to XMS
  157.             printf("Writing out used block %d\n", curBlock);
  158.             XMSParms.sourceHandle=0;
  159.             XMSParms.sourcePtr=XMSBuf;
  160.             XMSParms.destHandle=XMSHandle;
  161.             XMSParms.destPtr=(void far *) (((long)curBlock) *
  162.                                                BLOCKSIZE);
  163.             XMSParms.blockLength=BLOCKSIZE;
  164.             // pass a pointer to the parameters structure to
  165.             // the XMS Manager
  166.             _SI=FP_OFF(&XMSParms);
  167.             _AH=0x0B;
  168.             (*XMSFunc)();
  169.             if (_AX==0)
  170.             {
  171.                  printf("Error writing block %d!\n",curBlock);
  172.  
  173.                  CleanUpAndLeave();
  174.             }
  175.        }
  176.        // fetch block from XMS into XMSBuf buffer
  177.        printf("Getting XMS block %d\n",block);
  178.        XMSParms.sourceHandle=XMSHandle;
  179.        XMSParms.sourcePtr=(void far *) (((long)block) * BLOCKSIZE);
  180.        XMSParms.destHandle=0;
  181.        XMSParms.destPtr=XMSBuf;
  182.        XMSParms.blockLength=BLOCKSIZE;
  183.        _SI=FP_OFF(&XMSParms);
  184.        _AH=0x0B;
  185.        (*XMSFunc)();
  186.        if (_AX==0)
  187.        {
  188.             printf("Error reading block %d!\n",block);
  189.             CleanUpAndLeave();
  190.        }
  191.        curBlockDirty=FALSE;
  192.        curBlock=block;
  193.   }
  194.  
  195.   // PutVal() puts a value into the "big array" using
  196.   // GetCorrectBlock() to swap the buffer to/from XMS
  197.   // if necessary
  198.  
  199.   // You could improve performance in PutVal() and GetVal() by
  200.   // using bit-shifts instead of divides, and by using the '&'
  201.   // operator instead of '%' to find the position in XMSBuf.
  202.  
  203.   void PutVal(unsigned long loc, unsigned long val)
  204.   {
  205.        unsigned int block;
  206.        block=(int) (loc/(BLOCKSIZE/sizeof(long)));
  207.        if (block != curBlock) GetCorrectBlock(block);
  208.        // note that the current block in XMSBuf has been used so
  209.        // we won't forget to write it out later
  210.        curBlockDirty=TRUE;
  211.        // the buffer holds BLOCKSIZE bytes,
  212.        // or BLOCKSIZE/sizeof(long) long's)
  213.        XMSBuf[loc % (BLOCKSIZE/sizeof(long)) ] = val;
  214.   }
  215.  
  216.  
  217.   // GetVal() returns the value from a point in the "big array"
  218.   // using GetCorrectBlock() to swap buffer to/from XMS if
  219.   // necessary
  220.  
  221.   long GetVal(unsigned long loc)
  222.   {
  223.        unsigned int block;
  224.        block=(int) (loc/(BLOCKSIZE/sizeof(long)));
  225.        if (block != curBlock) GetCorrectBlock(block);
  226.        return( XMSBuf[loc % (BLOCKSIZE/sizeof(long)) ] );
  227.   }
  228.  
  229.   int main()
  230.   {
  231.        int kbAvail,largestAvail;
  232.        unsigned long i;
  233.  
  234.        if (XMSCheck) printf("XMS Available ...\n");
  235.        else
  236.        {
  237.             printf("XMS Not Available\n");
  238.             return(1);
  239.        }
  240.  
  241.        GetXMSEntry();
  242.  
  243.        XMSSize(&kbAvail,&largestAvail);
  244.        printf("Kilobytes Available: %d; Largest block: %dK\n",
  245.                  kbAvail,largestAvail);
  246.  
  247.        if (!GetBuf())
  248.             { printf("Error allocating buffer!\n");  return(1); }
  249.  
  250.        // We'll allocate space for 50,000 Long's (200,000 bytes)
  251.        // in our simulated array.
  252.  
  253.        if (!AllocXMS(sizeof(long)*50000L))
  254.             return(1);
  255.  
  256.        // put a lot of values in our simulated array, and read
  257.        // them back to make sure that they're out there
  258.  
  259.        for (i=0; i<50000L; i++)
  260.  
  261.             PutVal(i,i);
  262.        for (i=0; i<50000L; ++i)
  263.             if (GetVal(i)!=i)
  264.             { printf("Error: %lu != %lu\n",i,GetVal(i)); break; }
  265.  
  266.        CleanUpAndLeave();
  267.        return(0);
  268.   }
  269.